# -*- coding:utf-8 -*-
# @FileName : app\logger.py
# @Time     : 2025/11/28
# @Author   : 天空之城
"""
        初始化 Logger 类
        :param log_folder_path: 日志文件夹路径
        :param log_file_name: 日志文件名
        :param log_encode: 日志文件编码，默认为 UTF-8
        :param log_level: 日志级别，默认为 INFO
        """
import datetime
import inspect
import logging
import os
from functools import wraps


def logger_decor(func):
    @wraps(func)
    def wrapper(self, msg, *args, **kwargs):
        try:
            caller_frame = inspect.currentframe().f_back
            root_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
            filename = caller_frame.f_code.co_filename.replace(root_path, '')[1:]
            func_name = caller_frame.f_code.co_name
            lineno = caller_frame.f_lineno
        except Exception as err:
            print(str(err))
        finally:
            return func(self, msg, *args, **kwargs)

    return wrapper


class Logger:
    class CustomFilter(logging.Filter):
        def filter(self, record):
            # 获取记录日志时调用堆栈的帧列表
            frame_list = inspect.stack()

            # 查找记录日志的帧
            for frame in frame_list:
                # 确保跳过 logger 类和 logging 模块自身的帧
                if frame.filename == __file__ or 'logging' in frame.filename:
                    continue

                # 找到第一个不属于 logger 类和 logging 模块的帧，即为记录日志的调用帧
                record.filename = os.path.basename(frame.filename)  # 只获取文件名
                record.lineno = frame.lineno
                break

            return True

    @staticmethod
    def get_log_file_path(log_folder_path, log_file_name):
        today = datetime.datetime.now().strftime('%Y-%m-%d')
        log_file_name = str(log_file_name).replace('.log', f'_{today}.log')
        log_file_path = os.path.join(log_folder_path, log_file_name)
        return log_file_path

    def __init__(self, log_folder_path, log_file_name, log_encode='UTF-8', log_level='INFO'):
        
        if not os.path.exists(log_folder_path):
            os.makedirs(log_folder_path)

        # 构建日志文件路径
        log_file_path = self.get_log_file_path(log_folder_path, log_file_name)

        # 初始化日志编码和日志文件路径
        self.__log_encode = log_encode
        self.__log_file_path = log_file_path

        # 创建logger对象并设置日志级别
        self._logger = logging.getLogger(log_file_name)
        self._logger.setLevel(log_level.upper())  # 设置最低日志级别为 DEBUG，由 Handler 控制实际输出

        # 创建日志格式
        formatter = logging.Formatter(
            '%(asctime)s - %(filename)s - %(levelname)s - %(funcName)s - %(lineno)d - %(message)s')

        file_handler = logging.FileHandler(log_file_path, encoding=log_encode)
        file_handler.setLevel(log_level.upper())  # 根据传入参数设置文件处理器的日志级别
        file_handler.setFormatter(formatter)
        self._logger.addHandler(file_handler)

        # 创建控制台处理器并添加到logger
        console_handler = logging.StreamHandler()
        console_handler.setLevel(log_level.upper())
        console_handler.setFormatter(formatter)
        self._logger.addHandler(console_handler)

        # 添加自定义过滤器
        custom_filter = self.CustomFilter()
        self._logger.addFilter(custom_filter)

    @logger_decor
    def debug(self,  *args):
        message = " ".join(map(str, args))
        self._logger.debug(message)

    @logger_decor
    def info(self, *args):
        message = " ".join(map(str, args))
        self._logger.info(message)

    @logger_decor
    def warning(self, *args):
        message = " ".join(map(str, args))
        self._logger.warning(message)

    @logger_decor
    def error(self, *args):
        message = " ".join(map(str, args))
        self._logger.error(message)

    @logger_decor
    def critical(self, *args):
        message = " ".join(map(str, args))
        self._logger.critical(message)

    def exception(self, *args):
        message = " ".join(map(str, args))
        self._logger.exception(message)